/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.nViron.Tiles;

import instar.dg.Tiles.TilesCache;
import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import org.nViron.Render.RendererGL;
import org.nViron.nvSim.nvSimulator;

/**
 *
 * @author Roland
 */
public class TileSourceGL extends TileSource {

    private RendererGL rendererGL;

    public TileSourceGL(nvSimulator simulator) {
        super(simulator);
    }

    public void setRenderer(RendererGL rendererGL) {
        super.setRenderer(rendererGL);
        this.rendererGL = rendererGL;
    }

    @Override
    public void render() {
        if (rendererGL == null || rendererGL.getDrawable() == null) {
            return;
        }

        super.render();
    }

    @Override
    protected VisibleTile createVisibleTile(int x, int y, long mapId) {
        return new VisibleTileGL(x, y, mapId);
    }

    protected class TileTexGL extends TileTex {

        private int texID;

        public int getTexID() {
            return texID;
        }

        public void setTexID(int texID) {
            this.texID = texID;
        }

        public TileTexGL(int x, int y, long mapID) {
            super(x, y, mapID);
            texID = -1;
        }
    }

    protected class VisibleTileGL extends VisibleTile {

        public VisibleTileGL(int x, int y, long mapID) {
            super(x, y, mapID);
        }

        @Override
        protected void render() {
            TileTexGL tileTex = (TileTexGL) textureCache.get(x, y, mapID);
            if (tileTex != null) {
                GL gl = rendererGL.getDrawable().getGL();
                gl.glColor4f(1, 1, 1, 1.0f);
                if (tileTex.getTexID() == -1 && tileTex.getBuffer() != null) { // loaded but no texture generated yet
                    generateGLTexture(tileTex);
                }
                if (tileTex.getTexID() == -1) { // not loaded yet
                    // TODO render Dummy
                    // TODO check how old it is and perhaps delete it to enable reloading ...
                    gl.glColor4f(0.5f, 0.25f, 0.25f, 1.0f);
                } else {
                    gl.glBindTexture(gl.GL_TEXTURE_2D, tileTex.getTexID());
                    gl.glEnable(gl.GL_TEXTURE_2D);
                }
                float yOffset = 0;
                gl.glBegin(gl.GL_QUADS);
                gl.glNormal3f(0, 1, 0);
                gl.glTexCoord2f(0, 0);
                gl.glVertex3f(aaBox.corner.x, yOffset, aaBox.corner.z);
                gl.glTexCoord2f(0, 1);
                gl.glVertex3f(aaBox.corner.x, yOffset, aaBox.corner.z + aaBox.z);
                gl.glTexCoord2f(1, 1);
                gl.glVertex3f(aaBox.corner.x + aaBox.x, yOffset, aaBox.corner.z + aaBox.z);
                gl.glTexCoord2f(1, 0);
                gl.glVertex3f(aaBox.corner.x + aaBox.x, yOffset, aaBox.corner.z);
                gl.glEnd();
                gl.glDisable(gl.GL_TEXTURE_2D);
                // render outline
//                gl.glBegin(gl.GL_LINE_STRIP);
//                gl.glColor4f(0, 1, 0, 0.5f);
//                gl.glVertex3f(aaBox.corner.x, yOffset + 0.0001f, aaBox.corner.z);
//                gl.glVertex3f(aaBox.corner.x, yOffset + 0.0001f, aaBox.corner.z + aaBox.z);
//                gl.glVertex3f(aaBox.corner.x + aaBox.x, yOffset + 0.0001f, aaBox.corner.z + aaBox.z);
//                gl.glVertex3f(aaBox.corner.x + aaBox.x, yOffset + 0.0001f, aaBox.corner.z);
//                gl.glEnd();
                // render line to center of frustum
//                gl.glBegin(gl.GL_LINES);
//                gl.glColor4f(1, 0, 0, 0.5f);
//                gl.glVertex3f(aaBox.corner.x, yOffset + 0.0001f, aaBox.corner.z);
//                gl.glVertex3f(rendererGL.getFrustum().gCent.x, yOffset + 0.0001f, rendererGL.getFrustum().gCent.z);
//                gl.glEnd();
            } else {
                // create new empty texture
                tileTex = new TileTexGL(x, y, mapID);
                textureCache.add(tileTex);
                // load data from tileserver
                TilesCache.getInstance().getTile(mapID, x, y);
            }
        }

        private void generateGLTexture(TileTexGL tileTex) {
            GL gl = rendererGL.getDrawable().getGL();
            int id[] = new int[1];
            gl.glGenTextures(1, id, 0);
            gl.glBindTexture(gl.GL_TEXTURE_2D, id[0]);
            // use mipmaps
//            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR);
//            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
//            GLU glu = rendererGL.getGlu();
//            glu.gluBuild2DMipmaps(gl.GL_TEXTURE_2D, 1, tileTex.getWidth(), tileTex.getHeight(), gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, tileTex.getBuffer());
            // use normal texture
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE);
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE);
            gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_LUMINANCE, tileTex.getWidth(), tileTex.getHeight(), 0, gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, tileTex.getBuffer());
            tileTex.releaseBuffer();
            tileTex.setTexID(id[0]);
        }
    }
}
